package com.miku.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.util.Base64;

/**
 * io相关操作，注意，所有的操作路径，请以/为切分
 * @author 杜金伟 [2016年3月10日 下午10:59:55]
 */
public class IOUtils {
	
	public static boolean fileExists(String file){
		return (new File(file)).exists();
	}
	
	//目录预处理，对/结尾的，直接返回，否则在尾部加上/返回
	public static String dirPreprocess(String dir){
		if(dir.endsWith("/")){
			return dir;
		}else{
			return dir + "/";
		}
	}
	
	/**
	 * 给定路径，创建目录，可以直接创建整个路径的所有目录
	 * @param path   给定一个路径
	 * @return 
	 */
	public static boolean createDirs(String path){
		File f = new File(path);
		return f.exists() || f.mkdirs();
	}
	
	/**
	 * 给定路径，读取其内容到byte[]
	 * @param path 文件全路径
	 * @return 读取失败，返回null
	 */
	public static byte[] readFile(String path){
		FileInputStream in = null;
		try{
			File hf = new File(path);
			in = new FileInputStream(hf);
			long len = hf.length();
			byte[] bs = new byte[(int)len];
			in.read(bs);
			return bs;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return null;
	}
	
	/**
	 * 保存数据到指定路径
	 * @param path  指定路径
	 * @param bys    保存的数据
	 * @return 
	 */
	public static boolean saveToFile(String path, byte[] bys){
		if(path == null || bys == null) return false;
		File f = new File(path);
		if(!f.getParentFile().exists()){
			f.getParentFile().mkdirs();
		}
		
		boolean ret = false;
		FileOutputStream os = null;
		try{
			os = new FileOutputStream(f);
			os.write(bys);
			os.close();
			ret = true;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ret;
	}
	
	/**
	 * 保存文件，返回md5，基于数据，名称以md5命名
	 * @param dir  		指定保存的目录
	 * @param suffix	指定保存的后缀，例如：.jpg
	 * @param bys		指定数据
	 * @return
	 */
	public static String saveToFileMD5(String dir, String suffix, byte[] bys){
		if(bys == null) return null;
		
		String md5 = MD5.fromBytes(bys);
		File f = new File(dirPreprocess(dir) + md5 + suffix);
		if(!f.getParentFile().exists()){
			f.getParentFile().mkdirs();
		}
		
		boolean ret = false;
		FileOutputStream os = null;
		try{
			os = new FileOutputStream(f);
			os.write(bys);
			os.close();
			ret = true;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ret ? md5 : null;
	}
	
	/**
	 * 保存multiPartfile为文件，指定路径
	 * @param path	保存路径
	 * @param file		文件数据
	 * @return
	 */
	public static boolean saveMultipartToFile(String path, MultipartFile file){
		if(file == null || org.apache.commons.lang3.StringUtils.isEmpty(path) || file.isEmpty()){
			return false;
		}
	
		boolean ok = false;
		try {
			file.transferTo(new File(path));
			ok = true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ok;
	}
	
	/**
	 * 保存multiPartFile到文件，md5命名，返回md5
	 * @param dir		保存的目录
	 * @param suffix	后缀
	 * @param mfile	文件
	 * @return
	 */
	public static String saveMultipartToFileMD5(String dir, String suffix, MultipartFile mfile){
		if(mfile == null || org.apache.commons.lang3.StringUtils.isEmpty(dir) || mfile.isEmpty()){
			return null;
		}
		
		dir=dirPreprocess(dir);
		File dd = new File(dir);
		if(!dd.exists()){
			dd.mkdirs();
		}
		
		FileOutputStream os = null;
		String md5 = null;
		try{
			byte[] bys = mfile.getBytes();
			md5 = MD5.fromBytes(bys);
			File fs = new File(dir + md5 + ".jpg");
			os = new FileOutputStream(fs);
			os.write(bys);
			os.close();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try {
				if(os != null)
					os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return md5;
	}
	
	/**
	 * 保存数据到文件，md5
	 * @param dir	保存的目录
	 * @param bs	保存的数据
	 * @return
	 */
	public static String saveBytesToFileMD5(String dir, byte[] bs){
		if(bs == null || org.apache.commons.lang3.StringUtils.isEmpty(dir)){
			return null;
		}
		
		dir=dirPreprocess(dir);
		File dd = new File(dir);
		if(!dd.exists()){
			dd.mkdirs();
		}
		
		FileOutputStream os = null;
		String md5 = null;
		try{
			md5 = MD5.fromBytes(bs);
			File fs = new File(dir + md5 + ".jpg");
			os = new FileOutputStream(fs);
			os.write(bs);
			os.close();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try {
				if(os != null)
					os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return md5;
	}
	
	/**
	 * 保存文件数据来自base64编码的数据
	 * @param path		路径
	 * @param data		数据
	 * @return
	 */
	public static boolean saveFromBase64(String path, String data){
		byte[] d = Base64.decodeFast(data);
		return saveToFile(path, d);
	}
	
	public static boolean respFile(String file, HttpServletResponse resp){
		File f = new File(file);
		InputStream is = null;
		OutputStream os = null;
		try{
			is = new FileInputStream(f);
			os = resp.getOutputStream();
			
			byte bs[] = new byte[4096];
			int r = 0;
			while((r = is.read(bs)) > 0){
				os.write(bs, 0, r);
			}
		}catch(Exception e){
			return false;
		}finally{
			try {
				if(is != null)	is.close();
				if(os != null) os.close();
			} catch (IOException e) {
			}
		}
		return true;
	}
	
	//保存文件，从inputstream
	public static boolean saveToFile(String file, InputStream in){
		boolean succ = false;
		File f = new File(file);
		FileOutputStream out = null;
		try{
			out = new FileOutputStream(f);
			byte[] buf = new byte[4096];
			int rlen = 0;
			while((rlen = in.read(buf)) != -1)
				out.write(buf, 0, rlen);
			
			succ = true;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(out != null){
				try {
					out.close();
				} catch (IOException e) {}
			}
		}
		return succ;
	}
	
	 /**
	    * 使用文件通道的方式复制文件
	    * 
	    * @param src 			源文件
	    * @param dst			复制到的新文件
	    */
	    public static void copyTo(String src, String dst) {
	        FileInputStream fi = null;
	        FileOutputStream fo = null;
	        FileChannel in = null;
	        FileChannel out = null;
	        File s = new File(src);
	        File t = new File(dst);
	        try {
	            fi = new FileInputStream(s);
	            fo = new FileOutputStream(t);
	            in = fi.getChannel();//得到对应的文件通道
	            out = fo.getChannel();//得到对应的文件通道
	            in.transferTo(0, in.size(), out);//连接两个通道，并且从in通道读取，然后写入out通道
	        } catch (IOException e) {
	            e.printStackTrace();
	        } finally {
	        	try{if(fi != null) fi.close();}catch(Exception e){}
	        	try{if(in != null) in.close();}catch(Exception e){}
	        	try{if(fo != null) fo.close();}catch(Exception e){}
	        	try{if(out != null) out.close();}catch(Exception e){}
	        }
	    }
}
